package org.lundberg.podcasts;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Calendar;

import org.lundberg.podcasts.types.Channel;
import org.lundberg.podcasts.util.DownloadIconTask;
import org.lundberg.podcasts.util.PodcastDB;
import org.lundberg.podcasts.util.Util;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;

public class ItemsActivity extends ListActivity
{
	private static final int MARK_LISTENED_MENU_ITEM = Menu.FIRST;
	private static final int DOWNLOAD_MENU_ITEM = Menu.FIRST+1;
	private static final String[] COLUMNS = new String[] {"guid",
												        "title",
												        "pubDate",
												        "listened",
												        "size",
												        "_id"};
	private SQLiteDatabase db = null;
	private SimpleCursorAdapter mAdapter;
	private Channel channel;
	private boolean filterItems = false;
	private final Handler mUpdateHandler = new Handler();
	private boolean isDownloadServiceBound = false;
	private DownloadService mDownloadService = null;
	private final ServiceConnection mConnection = new ServiceConnection() {
	    @Override
		public void onServiceConnected(ComponentName className, IBinder service) {
	    	mDownloadService = ((DownloadService.LocalBinder)service).getService();
	    }
	    @Override
		public void onServiceDisconnected(ComponentName className) {
	    	mDownloadService = null;
	    }
	};
	
	
	
	@Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);
        setContentView(R.layout.items_layout);
        
        getActionBar().setDisplayHomeAsUpEnabled(true);
        
        registerForContextMenu(getListView());
        
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
		this.filterItems = settings.getBoolean("filter_items", false);
        
        this.channel = getIntent().getParcelableExtra("channel");
        
		setTitle(channel.title);
        
        final ImageView icon = (ImageView) findViewById(R.id.icon);
        
        ViewTreeObserver vto = icon.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
            	new ItemsActivityDownloadIconTask(getApplicationContext(), channel.id, icon).execute();
            	icon.getViewTreeObserver().removeOnPreDrawListener(this);
                return true;
            }
        });
        
		
		TextView title = (TextView) findViewById(R.id.title);
		title.setText(channel.title);
    }
	
	
	


	@Override
	public void onResume()
	{
		super.onResume();
    	
		if (db == null || db.isOpen() == false) {
			PodcastDB helper = new PodcastDB(getApplicationContext());
			db = helper.getReadableDatabase();
		}
		
		Cursor cursor = db.query(false, PodcastDB.ITEMS_TABLE, COLUMNS,
            			"channel_id="+channel.id+(filterItems ? " AND listened=0" : ""), null, null, null, "pubDate DESC", null);
		
		startManagingCursor(cursor);
		
		mAdapter = new ListAdapter(getApplicationContext(), R.layout.items_row, cursor,
											new String[] {"title", "pubDate", "size"},
											new int[] {R.id.title, R.id.date, R.id.size});
		setListAdapter(mAdapter);
		
        
        if (!isDownloadServiceBound) {
    		
    		bindService(new Intent(getApplicationContext(),  DownloadService.class), mConnection, Context.BIND_AUTO_CREATE);
    		isDownloadServiceBound = true;
    	}
	}
	
	
	
	@Override
	public void onPause()
	{
		super.onPause();
		
		SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
		Editor editor = settings.edit();
		editor.putBoolean("filter_items", filterItems);		
		editor.commit();
	}
	
	
	
	@Override
	public void onDestroy()
	{
		super.onDestroy();
		
		if (isDownloadServiceBound) {
    		unbindService(mConnection);
    		isDownloadServiceBound = false;
    	}
		
		db.close();
	}
	
	
	
	@Override
	public void onListItemClick(ListView listView, View view, int position, long id)
	{
		// open PlayerActivity
		Intent intent = new Intent(this, PlayerActivity.class);
		intent.putExtra("guid", mAdapter.getCursor().getString(0));
		intent.putExtra("queue_type", "Channel");
		startActivity(intent);
	}
	
	
	
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
	{
		if (mAdapter.getCursor().getInt(3) == 1) {
			
			menu.add(0, MARK_LISTENED_MENU_ITEM, 0, "Mark as not listened");
		}
		else {
			
			menu.add(0, MARK_LISTENED_MENU_ITEM, 0, "Mark as listened");
		}
		
		if (mDownloadService.isDownloading(mAdapter.getCursor().getString(0))) {
    		
    		menu.add(0, DOWNLOAD_MENU_ITEM, Menu.NONE, "Cancel download");
    	}
	    else if (Util.isDownloaded(mAdapter.getCursor().getString(0))) {
    		
    		menu.add(0, DOWNLOAD_MENU_ITEM, Menu.NONE, "Remove download");
    	}
    	else {
    	
    		menu.add(0, DOWNLOAD_MENU_ITEM, Menu.NONE, "Download");
    	}
		
	}
	
	
	/*
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {

    	super.onCreateOptionsMenu(menu);
    	
    	MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.items_menu, menu);
        
        MenuItem showAll = menu.getItem(1);

        if (filterItems) {
    		showAll.setTitle("Show All");
    	}
    	else {
    		showAll.setTitle("Hide Listened");
    	}
    	
    	return true;
    }
    */
	
	
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem menuItem)
    {
		// Get the info on which item was selected
	    AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuItem.getMenuInfo();
	    Cursor cursor = null;
	    if (info != null) {
	    	cursor = (Cursor)mAdapter.getItem(info.position);
	    }
	    else if (mAdapter.getCount() > 0) {
	    	cursor = (Cursor)mAdapter.getItem(0);
	    }
		
	    switch (menuItem.getItemId())
    	{
		case R.id.refresh_menu_item:
						Intent serviceIntent = new Intent(this, UpdateService.class);
						serviceIntent.putExtra("channels", new int[] {channel.id});
						serviceIntent.putExtra("force_update", true);
						startService(serviceIntent);
						break;
						
		case R.id.unsubscribe_menu_item:
						showDialog(R.id.unsubscribe_menu_item);
						break;
						
		case R.id.preferences_menu_item:
						Intent prefIntent = new Intent(this, PodcastPreferenceActivity.class);
						startActivity(prefIntent);
						break;
						
		case R.id.show_hide_menu_item:
						filterItems = !filterItems;
						Log.d("ItemsActivity", "onMenuItemSelected - filterItems: "+filterItems);
						String where = "channel_id="+channel.id + (filterItems ? " AND listened=0" : "");
						menuItem.setTitle(filterItems ? "Show All" : "Hide Listened");		
						PodcastDB helper = new PodcastDB(this);
						SQLiteDatabase db = helper.getReadableDatabase();
						mAdapter.changeCursor(db.query(PodcastDB.ITEMS_TABLE, PodcastDB.ITEMS_COLUMNS, where, null, null, null, "(listened=1),pubDate"));
						break;
						
		case MARK_LISTENED_MENU_ITEM:
						markItemListened(cursor.getString(0), (cursor.getInt(3) == 0));
						mAdapter.getCursor().requery();
						break;
						
		case R.id.mark_listened_all_menu_item:
						if (markListened(null)) {
							mAdapter.getCursor().requery();
						}
						break;
						
		case R.id.mark_listened_older_menu_item:
						Calendar cal = Calendar.getInstance();
						cal.setTimeInMillis(System.currentTimeMillis()-604800000);
						String date = Util.ISO8601_DATE_FORMAT.format(cal.getTime());
						if (markListened(date)) {
							mAdapter.getCursor().requery();
						}
						break;
						
		case DOWNLOAD_MENU_ITEM:
						final String guid = cursor.getString(0);
						if (Util.isDownloaded(guid))
						{
							File file = new File(Util.getPodcastFilename(guid));
							file.delete();
							mAdapter.getCursor().requery();
						}
						else
						{
							new Thread() {
								public void run() {
									Intent intent = new Intent(getApplicationContext(), DownloadService.class);
									if (mDownloadService.isDownloading(guid)) {
										intent.setAction(DownloadService.CANCEL);
										intent.putExtra("guid", guid);
									}
									else {
										intent.setAction(DownloadService.DOWNLOAD);
										ArrayList<String> guids = new ArrayList<String>(1);
										guids.add(guid);
										intent.putStringArrayListExtra("guid", guids);
									}
									startService(intent);
								}
							}.start();
						}
						break;
						
		case android.R.id.home:
			            // app icon in action bar clicked; go home
			            Intent intent = new Intent(this, MainActivity.class);
			            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			            startActivity(intent);
			            return true;
    	}
		
		return true;
    }
	
	
	
	@Override
    public Dialog onCreateDialog(int id, Bundle bundle)
    {
		if (id == R.id.unsubscribe_menu_item)
    	{
    		AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Unsubscribe");
            builder.setMessage("Are you sure you want to unsubscribe from "+getTitle()+"?");
            builder.setCancelable(true);
            builder.setNegativeButton(android.R.string.cancel, null);
            builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
                @Override
				public void onClick(DialogInterface dialog, int arg1) {

                	new Thread(new Runnable() {
                        @Override
						public void run() {
                        	
                        	PodcastDB.deleteChannel(getApplicationContext(), channel.id);
                        	
                        	mUpdateHandler.post(new Runnable() {
								@Override
								public void run() {
									mAdapter.getCursor().requery();
								}
							});
                        }
                    }).start();
                }
            });

            return builder.create();
    	}
		
		
		return null;
    }
	
	
	private class ListAdapter extends SimpleCursorAdapter
	{
		public ListAdapter (Context context, int layout, Cursor c, String[] from, int[] to) {
			super(context, layout, c, from, to);
		}
		
		@Override
		public void bindView(View view, Context context, Cursor c)
		{
			TextView title = (TextView)view.findViewById(R.id.title);
			title.setText(c.getString(1));
            
			Resources res = getResources();
			
            if (c.getInt(3) == 1) {
            	
            	title.setTextColor(res.getColor(R.color.gray));
            }
            else {
            	
            	title.setTextColor(res.getColor(R.color.white));
            }
            
            TextView date = (TextView)view.findViewById(R.id.date);
            date.setText(Util.getItemAge(c.getString(2)));
            
            TextView size = (TextView)view.findViewById(R.id.size);
            
            float fileSize = 0.0f;
            
            if (Util.isDownloaded(c.getString(0))) {
            	
            	fileSize = (c.getInt(4) > 0) ? toMegabytes(c.getInt(4)) : getFileSize(c.getString(0));
            	size.setTextColor(res.getColor(R.color.gray));
            }
            else {
            	
            	size.setTextColor(res.getColor(R.color.dark_gray));
            }
            
            size.setText(String.format(res.getString(R.string.size), fileSize));
		}
			
	}
	
	
	
	private class ItemsActivityDownloadIconTask extends DownloadIconTask
    {
		private WeakReference<Context> activity;
		
		public ItemsActivityDownloadIconTask(Context activity, int channel_id, ImageView view) {
    		
    		super(PodcastDB.getImageURL(activity, channel_id), view);
    		this.activity = new WeakReference<Context>(activity);
    	}
    	
    	@Override
    	public void onPreExecute() {
    		
    		networkAvailable = Util.isNetworkAvailable(activity.get());
    	}
    	
    	@Override
    	protected void onPostExecute(Bitmap bitmap)
    	{
    		if (bitmap != null)
    		{
    			ImageView view = imageViewReference.get();
    			
    			if (view != null)
    			{
	    			TransitionDrawable drawable = new TransitionDrawable(
							new Drawable[] {view.getDrawable(), new BitmapDrawable(bitmap)});
					
					view.setImageDrawable(drawable);
					drawable.setCrossFadeEnabled(true);
					drawable.startTransition(500);
    			}
    		}
    	}
    }
	
	
	
	private boolean markListened(String date)
	{
		PodcastDB helper = new PodcastDB(getApplicationContext());
		SQLiteDatabase db = helper.getReadableDatabase();
		String where = "channel_id="+channel.id+" AND listened=0";
		
		if (date != null) {
			where += " AND pubDate < '"+date+"'";
		}
		
		ContentValues values = new ContentValues();
    	values.put("listened", 1);
    	
    	int count = db.update(PodcastDB.ITEMS_TABLE, values, where, null);
    	
    	if (count > 0) {
    		
    		channel.new_items -= count;
    		values.clear();
    		values.put("new_items", channel.new_items);
    		db.update(PodcastDB.CHANNELS_TABLE, values, "_id="+channel.id, null);
    	}
    	
    	
    	helper.close();
    	
    	return (count > 0);
	}
	
	
	
	private void markItemListened(String guid, boolean listened)
	{
		PodcastDB helper = new PodcastDB(getApplicationContext());
    	SQLiteDatabase db = helper.getReadableDatabase();
    	ContentValues values = new ContentValues();
    	
    	values.put("listened", (listened ? 1 : 0));
    	
    	db.update(PodcastDB.ITEMS_TABLE, values, "guid='"+guid+"'", null);
    	
    	values.clear();
    	
    	channel.new_items = listened ? channel.new_items - 1 : channel.new_items + 1;
    	values.put("new_items", channel.new_items);
    	
    	db.update(PodcastDB.CHANNELS_TABLE, values, "_id="+channel.id, null);
    	
    	db.close();
    	helper.close();
	}
	
	
	
	private static float getFileSize(String guid)
	{
		File file = new File(Util.getPodcastFilename(guid));
		long length = file.length();
		
		if (length == 0) {
			file = new File(file.getAbsolutePath()+".tmp");
			length = file.length();
		}
		
		return toMegabytes(length);
	}
	
	
	
	private static float toMegabytes(long size)
	{
		return (size > 0) ? (size / 1048576.0f - 0.05f) : 0.0f;
	}
	
	
}
